<template>
  <div class="rich-editor">
    <div ref="editorRef" class="editor-container"></div>
    <div v-if="showWordCount" class="word-count">
      字数：{{ wordCount }}
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { createEditor, createToolbar } from '@wangeditor/editor'
import '@wangeditor/editor/dist/css/style.css'

const props = defineProps({
  // 编辑器内容
  modelValue: {
    type: String,
    default: ''
  },
  // 编辑器高度
  height: {
    type: [String, Number],
    default: 500
  },
  // 是否显示字数统计
  showWordCount: {
    type: Boolean,
    default: true
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false
  },
  // 占位文本
  placeholder: {
    type: String,
    default: '请输入内容'
  },
  // 上传图片配置
  uploadImageConfig: {
    type: Object,
    default: () => ({
      server: '',
      fieldName: 'file',
      maxFileSize: 10 * 1024 * 1024,
      maxNumberOfFiles: 10,
      allowedFileTypes: ['image/*'],
      meta: {},
      metaWithUrl: false,
      customInsert: null,
      customUpload: null
    })
  }
})

const emit = defineEmits(['update:modelValue', 'change', 'focus', 'blur'])

// 编辑器实例
const editorRef = ref(null)
let editor = null
let toolbar = null

// 字数统计
const wordCount = ref(0)

// 初始化编辑器
const initEditor = () => {
  // 创建编辑器配置
  const editorConfig = {
    placeholder: props.placeholder,
    readOnly: props.disabled,
    autoFocus: false,
    scroll: true,
    MENU_CONF: {
      uploadImage: {
        ...props.uploadImageConfig,
        // 上传图片失败
        onError(file, err, res) {
          ElMessage.error('图片上传失败')
          console.error('图片上传失败：', file, err, res)
        },
        // 上传图片成功
        onSuccess(file, res) {
          console.log('图片上传成功：', file, res)
        }
      }
    }
  }
  
  // 创建工具栏配置
  const toolbarConfig = {
    toolbarKeys: [
      'headerSelect',
      'bold',
      'italic',
      'underline',
      'through',
      'color',
      'bgColor',
      '|',
      'fontSize',
      'fontFamily',
      'lineHeight',
      '|',
      'bulletedList',
      'numberedList',
      'todo',
      '|',
      'emotion',
      'insertLink',
      'insertImage',
      'insertTable',
      'insertVideo',
      '|',
      'undo',
      'redo',
      '|',
      'fullScreen'
    ]
  }
  
  // 创建编辑器
  editor = createEditor({
    selector: editorRef.value,
    html: props.modelValue,
    config: editorConfig,
    mode: 'default'
  })
  
  // 创建工具栏
  toolbar = createToolbar({
    editor,
    selector: editorRef.value,
    config: toolbarConfig,
    mode: 'default'
  })
  
  // 监听内容变化
  editor.on('change', () => {
    const html = editor.getHtml()
    emit('update:modelValue', html)
    emit('change', html)
    
    // 更新字数统计
    wordCount.value = editor.getText().length
  })
  
  // 监听焦点事件
  editor.on('focus', () => {
    emit('focus')
  })
  
  editor.on('blur', () => {
    emit('blur')
  })
}

// 监听内容变化
watch(() => props.modelValue, (newVal) => {
  if (editor && newVal !== editor.getHtml()) {
    editor.setHtml(newVal)
  }
})

// 监听禁用状态变化
watch(() => props.disabled, (newVal) => {
  if (editor) {
    editor.setReadOnly(newVal)
  }
})

// 组件挂载时初始化编辑器
onMounted(() => {
  initEditor()
})

// 组件卸载时销毁编辑器
onBeforeUnmount(() => {
  if (editor) {
    editor.destroy()
    editor = null
  }
  if (toolbar) {
    toolbar.destroy()
    toolbar = null
  }
})

// 暴露方法
defineExpose({
  // 获取编辑器实例
  getEditor: () => editor,
  // 获取工具栏实例
  getToolbar: () => toolbar,
  // 获取编辑器内容
  getHtml: () => editor?.getHtml(),
  // 获取编辑器文本
  getText: () => editor?.getText(),
  // 设置编辑器内容
  setHtml: (html) => editor?.setHtml(html),
  // 清空编辑器内容
  clear: () => editor?.clear(),
  // 销毁编辑器
  destroy: () => {
    editor?.destroy()
    toolbar?.destroy()
    editor = null
    toolbar = null
  }
})
</script>

<style lang="scss" scoped>
.rich-editor {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  
  .editor-container {
    :deep(.w-e-text-container) {
      height: v-bind('typeof height === "number" ? `${height}px` : height') !important;
    }
  }
  
  .word-count {
    padding: 8px;
    text-align: right;
    color: #909399;
    font-size: 12px;
    border-top: 1px solid #dcdfe6;
  }
}
</style> 